#!/bin/bash
# Author: liuxu
# Date: 2025-01-08
# Description: Automated testing hip sample testcases

# TEST Usage:
# nohup bash hip-samples_test.sh  > ./result_samples_$(date +%Y%m%d).log 2>&1 &

# check dtk env
echo "hipcc path: $(which hipcc)" || source /opt/dtk/env.sh || (echo "[error]need to source dtk/env.sh" && exit 1)
echo -e "hy-smi:\n $(hy-smi)"

# Initialization variables
exec_ok_cnt=0
exec_fail_cnt=0
make_fail_cnt=0

# Arrays to store failed cases
make_fail_list=()
exec_fail_list=()

# Define the base path for the samples(0_Simple  1_Utilities  2_Advanced  3_HIPLibraries)
sample_base=${ROCM_PATH}/hip/samples

# Create an array of sample paths, excluding build directories
sample_paths=($(find "${sample_base}" -mindepth 2 -type d -not -path "*/build*" | sort))

for sample_path in "${sample_paths[@]}"; do
    echo -e "\n\n====== CWD: ${sample_path} ======"
    cd "${sample_path}" || (echo "[error] Failed to change directory to ${sample_path}" && exit 1)

    # Store the original path for later use
    original_path="${sample_path}"

    # Flag to track if we need to go back to the original directory after build
    build_subdir=false

    if [ -e Makefile ]; then
        if make clean >/dev/null && make >/dev/null 2>&1; then
            echo -e "[info] ls -l\n $(ls -l)"
        else
            ((make_fail_cnt++))
            make_fail_list+=("${sample_path}")
            echo "[error] make fail"
            continue
        fi
    elif [ -e CMakeLists.txt ]; then
        { [ -d build ] && rm -r build; } || true && mkdir -p build && cd build || exit $?
        build_subdir=true
        if cmake .. && make >/dev/null 2>&1; then
            echo -e "[info] ls -l\n $(ls -l)"
        else
            ((make_fail_cnt++))
            make_fail_list+=("${sample_path}")
            echo "[error] cmake fail"
            # Go back to original directory before continuing
            cd ..
            continue
        fi
    else
        echo "[warn] not found Makefile or CMakeLists.txt in ${sample_path}"
        continue
    fi

    # Search for an executable file in the current path that does not have a suffix or has an .out suffix
    executable_files=($(find . -maxdepth 1 -type f -executable \( ! -name "*.*" -o -name "*.out" \)))

    for exe in "${executable_files[@]}"; do
        # execute the sample testcase
        echo "[info] start to executed: ${exe}"

        # Get the full path of the executable for reporting
        if [ "$build_subdir" = true ]; then
            exe_full_path="${original_path}/build/${exe}"
        else
            exe_full_path="${original_path}/${exe}"
        fi

        if [[ ${exe} =~ hipDispatchEnqueueRateMT ]]; then
            # Run test as 'hipDispatchEnqueueRateMT <num_threads> <0-hipModuleLaunchKernel /1-hipLaunchKernelGGL>'
            ./"${exe}" 10 0
            result1=$?
            ./"${exe}" 20 1
            result2=$?
            if [ $result1 -eq 0 ] && [ $result2 -eq 0 ]; then
                ((exec_ok_cnt++))
                echo "[info] succeed to executed ${exe}"
            else
                ((exec_fail_cnt++))
                exec_fail_list+=("${exe_full_path}")
                echo "[error] failed to execute ${exe}"
            fi
        else
            ./"${exe}"
            if [ $? -eq 0 ]; then
                ((exec_ok_cnt++))
                echo "[info] succeed to executed ${exe}"
            else
                ((exec_fail_cnt++))
                exec_fail_list+=("${exe_full_path}")
                echo "[error] failed to execute ${exe}"
            fi
        fi
    done

    # If we built in a subdirectory, go back to the original directory
    if [ "$build_subdir" = true ]; then
        cd ..
    fi
done

echo "===================="
if [[ make_fail_cnt -eq 0 && exec_fail_cnt -eq 0 ]]; then
    # All passed
    echo -e "\e[32m[PASS]\e[0m All test cases passed. Total executed: ${exec_ok_cnt}"
else
    # Some cases failed
    echo -e "\e[31m[FAIL]\e[0m Test results:"
    echo "  - Passed: ${exec_ok_cnt}"
    echo "  - Failed: $((make_fail_cnt + exec_fail_cnt))"
    echo "    -- Compilation failures: ${make_fail_cnt}"

    # Print compilation failures
    if [ ${#make_fail_list[@]} -gt 0 ]; then
        echo "      Failed compilation cases:"
        for case in "${make_fail_list[@]}"; do
            echo "        ${case}"
        done
    fi

    echo "    -- Execution failures: ${exec_fail_cnt}"

    # Print execution failures
    if [ ${#exec_fail_list[@]} -gt 0 ]; then
        echo "      Failed execution cases:"
        for case in "${exec_fail_list[@]}"; do
            echo "        ${case}"
        done
    fi
fi

#(base) [root@b04r3n07 samples]# find $sample_dir  -mindepth 2  -type d | sort
#./0_Simple/2dshfl
#./0_Simple/assembly_to_executable
#./0_Simple/cmake_hip_add_executable
#./0_Simple/dynamic_shared
#./0_Simple/gpu_arch
#./0_Simple/hipDispatchLatency
#./0_Simple/hipEvent
#./0_Simple/inline_asm
#./0_Simple/matrixTranspose
#./0_Simple/module_api
#./0_Simple/module_api_global
#./0_Simple/occupancy
#./0_Simple/peer2peer
#./0_Simple/profiler
#./0_Simple/rdc_library
#./0_Simple/rdc_library/device_functions
#./0_Simple/rdc_library/host_functions
#./0_Simple/shared_memory
#./0_Simple/shfl
#./0_Simple/square
#./0_Simple/streams
#./0_Simple/texture_driver
#./0_Simple/unroll
#./1_Utilities/hipBusBandwidth
#./1_Utilities/hipInfo
#./2_Advanced/cooperative_groups
#./2_Advanced/hipDynamicParallelism
#./2_Advanced/hipGraph
